﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;

namespace D.WebApi.Core.Filters
{
    /// <summary>
    /// 异步资源缓存
    /// 使用方式： [ResourceCacheAsyncFilterAttribute(10)]
    /// </summary>
    public class ExtResourceCacheAsyncFilterAttribute : Attribute, IAsyncResourceFilter
    {

        private IMemoryCache _memoryCache;
        private readonly double _cacheTime;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="cacheTime">秒</param>
        public ExtResourceCacheAsyncFilterAttribute(double cacheTime = 30)
        {
            _cacheTime = cacheTime;
        }

        /// <summary>
        /// 异步请求资源缓存
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            // 获取缓存
            var cache = context.HttpContext.RequestServices.GetService(typeof(IMemoryCache));
            if (cache == null)
            {
                return;
            }

            _memoryCache = cache as IMemoryCache;

            var apiResourceCacheKey = GetCacheKey(context.HttpContext);
            var result = _memoryCache.Get(apiResourceCacheKey);
            if (result != null)
            {
                context.Result = result as IActionResult;
            }

            if (result == null && context.Result != null)
            {
                _memoryCache.Set(apiResourceCacheKey, context.Result, DateTime.Now.AddSeconds(_cacheTime));
            }
        }

        /// <summary>
        /// 获取每个唯一请求的缓存 key
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private string GetCacheKey(HttpContext context)
        {
            var requestId = context.TraceIdentifier.Split(':')[0];
            return $"{requestId}=>{context.Request.Path.ToString()?.ToLower()}";
        }
    }
}
